package com.zyj.core.builder;

import com.zyj.core.config.Configuration;
import com.zyj.core.io.Resources;
import com.zyj.core.utils.DocumentUtils;
import org.apache.commons.dbcp.BasicDataSource;
import org.dom4j.Document;
import org.dom4j.Element;

import java.io.InputStream;
import java.util.List;
import java.util.Properties;

/**
 * 用来解析全局配置文件的
 */
public class XMLConfigBuilder {

    /**
     * 持有全局配置对象
     */
    private Configuration configuration;

    public XMLConfigBuilder() {

        //在XMLConfigBuilder构建者创建的时候，同步创建全局配置对象
        this.configuration = new Configuration();
    }

    /**
     * <environments default="dev">
     * 		<environment id="dev">
     * 			<!-- 配置数据源信息 -->
     * 			<dataSource type="DBCP">
     * 				<property name="db.password" value="root"></property>
     * 				<property name="db.driver" value="com.mysql.jdbc.Driver"></property>
     * 				<property name="db.url"
     * 					value="jdbc:mysql://39.105.204.66:3306/kkb?characterEncoding=utf-8"></property>
     * 				<property name="db.username" value="root"></property>
     * 			</dataSource>
     * 		</environment>
     * 	</environments>
     */

    /**
     * 解析全局配置文件
     * @param rootElement
     * @return
     */
    public Configuration parseCofiguration(Element rootElement) {
        Element environments = rootElement.element("environments");
        // 解析环境配置，数据库配置
        parseEnvironments(environments);

        Element mappers = rootElement.element("mappers");
        // 解析用户配置文件
        parseMappers(mappers);

        return configuration;
    }

    /**
     * 解析环境配置environment标签
     *
     * @param environments
     */
    private void parseEnvironments(Element environments) {
        String aDefault = environments.attributeValue("default");

        List<Element> environmentList = environments.elements("environment");

        // 循环解析每一个environment标签
        for (Element environment : environmentList) {
            String id = environment.attributeValue("id");
            if (aDefault.equals(id)) {
                parseDataSource(environment);
            }
        }
    }

    /**
     * 解析数据库配置dataSource标签
     *
     * @param environment
     */
    private void parseDataSource(Element environment) {
        Element dataSource = environment.element("dataSource");
        String type = dataSource.attributeValue("type");
        if ("DBCP".equals(type)) {
            BasicDataSource ds = new BasicDataSource();

            // 解析xml中的perperty标签
            Properties properties = parseProperties(dataSource);

            ds.setDriverClassName(properties.getProperty("db.driver"));
            ds.setUrl(properties.getProperty("db.url"));
            ds.setUsername(properties.getProperty("db.username"));
            ds.setPassword(properties.getProperty("db.password"));

            configuration.setDataSource(ds);
        }
    }

    /**
     * 解析property标签
     * @param dataSource
     * @return
     */
    private Properties parseProperties(Element dataSource) {
        List<Element> propertyList = dataSource.elements("property");
        Properties properties = new Properties();
        for (Element property : propertyList) {
            String name = property.attributeValue("name");
            String value = property.attributeValue("value");
            properties.put(name, value);
        }
        return properties;
    }

    /**
     * <!-- 映射文件加载 -->
     * 	<mappers>
     * 		<!-- resource指定映射文件的类路径 -->
     * 		<mapper resource="mapper/UserMapper.xml"></mapper>
     * 	</mappers>
     */

    /**
     * 解析用户配置文件mapper标签
     * @param mappers
     */
    private void parseMappers(Element mappers) {
        List<Element> mapperList = mappers.elements("mapper");
        for (Element mapper : mapperList) {

            // 得到mapper标签的resource属性
            String resource = mapper.attributeValue("resource");

            // 根据resource属性中所执行的mapper.xml用户配置文件的路径加载输入流
            // 获取配置文件对应的流对象
            InputStream inputStream = Resources.getResourceAsStream(resource);

            // 获取配置文件对应的Document对象
            Document document = DocumentUtils.createDocument(inputStream);

            // 传全局配置对象进去接收用户配置文件中的信息，即用户配置文件的解析结果存入configuration对象
            // 按照指定的语义去解析Document文档对象
            // 使用XMLMapperBuilder构建解器析mapper文件
            XMLMapperBuilder mapperBuilder = new XMLMapperBuilder(configuration);

            // 调用构建器中的方法解析mapper文件
            mapperBuilder.parseMapper(document.getRootElement());
        }
    }


}
